Future generations of multiple core processors and multiple thread processors will provide an increasing number of threads on a single die. To exploit the computational power of these processors, alone and in multiple processor groupings, language runtimes must scale to a large number of threads and provide new primitives that simplify concurrent programming. In a cache-coherent shared memory platform, a memory allocator is used to allocate memory to each thread. The memory allocator plays an important role in scalability and cache locality optimizations. To enable applications to exploit concurrency to the maximum, the memory allocator needs to employ non-blocking algorithms to avoid becoming a scalability bottleneck. However, transactional programming, which provides a powerful tool for easing concurrent programming; is not integrated with memory allocation and deallocation.
There is a tension between explicit memory management and optimistic concurrency that might be used in software transactional memory. Explicit memory management relies on the application writer to know when a piece of memory is no longer going to be referenced by other parts of the application. Software transactional memory and, more generally, optimistic concurrency predicts that the state of the heap will not change until the transaction commits. The software transaction memory mechanism checks for potential changes when the transaction commits. While a transaction that uses an object that is being freed will abort, the internal mechanisms of the transaction operate best if the memory is not reclaimed until all potential conflicts have been detected.
This tension has been relieved through reference counting, hazard pointers, etc. However, these approaches require atomic operations when accessing pointers to shared memory which makes them expensive to implement.
This tension has also been relieved by requiring the application to execute a series of instructions at every read and write operation to a shared pointer. These operations essentially added the shared pointer to a “root set”. The memory manager would traverse the root set to figure out whether objects were reachable. Traversing the root set may be impractical for large synchronization blocks.
Space leaks in the presence of large running transactions present additional difficulties. Space leaks may be avoided in memory allocation/deallocation inside transactions by deferring the freeing of memory until a transaction commits. While this is semantically correct, it does not protect from space leaks in the presence of large transactions.